import blue
import base
import util
import log
import sys
import os
import const
import marshalstrings

class Settings():

    class Section():

        def __init__(self, datastore, dirtyFlag):
            self._Section__values = datastore
            self._Section__dirty = dirtyFlag



        def __str__(self):
            return ('Section instance, %s entries.' % len(self._Section__values))



        def __repr__(self):
            s = (self.__str__() + '\n')
            for (k, v,) in self._Section__values.iteritems():
                s += ('  %s:\t[%s] %s\n' % (k,
                 util.FmtDate(v[0]),
                 v[1]))

            return s



        def Get(self, key, defaultValue):
            if (key in self._Section__values):
                value = self._Section__values[key][1]
                self.Set(key, value)
                return value
            else:
                return defaultValue



        def Set(self, key, value):
            self._Section__values[key] = (blue.os.GetTime(), value)
            self._Section__dirty[0] = 1



        def Delete(self, key):
            if (key in self._Section__values):
                del self._Section__values[key]
                self._Section__dirty[0] = 1



        def __contains__(self, key):
            return (key in self._Section__values)



        def __keys__(self):
            return self._Section__values.keys()




    def __init__(self, filename, autoSaveSecs = 120):
        self._Settings__filename = filename
        self._Settings__dirty = [0]
        self._Settings__datastore = {}
        data = None
        try:
            fn = blue.rot.PathToFilename(filename)
            data = blue.win32.AtomicFileRead(fn)
        except:
            pass
        if data:
            try:
                self._Settings__datastore = marshalstrings.LoadOld(data[0])
                for (k, v,) in self._Settings__datastore.iteritems():
                    self.__dict__[k] = self.Section(v, self._Settings__dirty)

            except:
                log.LogException()
                sys.exc_clear()
        self.timeoutTimer = base.AutoTimer((autoSaveSecs * 1000), self.WriteToDisk)



    def Unload(self):
        self.timeoutTimer = None
        self.FlushOldEntries()
        self.WriteToDisk()



    def Save(self):
        self.FlushOldEntries()
        self.WriteToDisk()



    def __str__(self):
        return ("Settings instance '%s', %s sections." % (self._Settings__filename, len(self._Settings__datastore)))



    def __repr__(self):
        s = (self.__str__() + '\n')
        for (k, v,) in self._Settings__datastore.iteritems():
            s += ('  %s:\t%s\n' % (k, `v`))

        return s



    def GetSection(self, sectionName):
        if (sectionName in self.__dict__):
            return self.__dict__[sectionName]
        else:
            d = {}
            section = self.Section(d, self._Settings__dirty)
            self._Settings__datastore[sectionName] = d
            self.__dict__[sectionName] = section
            return section



    def FlushOldEntries(self, lastModified = None):
        if (lastModified is None):
            lastModified = (blue.os.GetTime() - (45 * const.DAY))
        for (k, v,) in self._Settings__datastore.iteritems():
            for key in v.keys():
                if (v[key][0] <= lastModified):
                    del v[key]


        self._Settings__dirty[0] = 1



    def WriteToDisk(self):
        if self._Settings__dirty[0]:
            self._Settings__dirty[0] = 0
            fn = blue.rot.PathToFilename(self._Settings__filename)
            try:
                if (os.access(fn, os.F_OK) and (not os.access(fn, os.W_OK))):
                    os.chmod(fn, 438)
                blue.win32.AtomicFileWrite(fn, marshalstrings.SaveNotable(self._Settings__datastore))
            except Exception:
                log.LogException()
                sys.exc_clear()




def LoadSettings(subSettings = (), subSections = ()):
    import __builtin__
    if hasattr(__builtin__, 'settings'):
        for (subName, identifier,) in subSettings:
            if hasattr(settings, subName):
                section = getattr(settings, subName, None)
                section.Unload()
                setattr(settings, subName, None)

        settings.FlushOldEntries()
        settings.WriteToDisk()
    else:
        pcsettings = Settings((blue.os.settingspath + 'pc.dat'), 60)
        for subSection in subSections:
            pcsettings.GetSection(subSection)

        __builtin__.settings = pcsettings
    for (subName, identifier,) in subSettings:
        _settings = Settings((blue.os.settingspath + ('%s_%s.dat' % (subName, (identifier or '_')))), 62)
        for subSection in subSections:
            _settings.GetSection(subSection)

        setattr(settings, subName, _settings)

    return settings


exports = {'util.Settings': Settings,
 'util.LoadSettings': LoadSettings}

